package com.uam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uam.common.constant.Constants;
import com.uam.common.exception.CustomException;
import com.uam.db.mapper.RoleMapper;
import com.uam.db.mapper.UserListMapper;
import com.uam.db.mapper.UserMapper;
import com.uam.db.mapper.UserRoleMapper;
import com.uam.db.model.dto.UserListDTO;
import com.uam.db.model.entity.User;
import com.uam.db.model.entity.UserRole;
import com.uam.db.model.vo.Login;
import com.uam.db.model.vo.LoginUser;
import com.uam.db.model.vo.UserListVO;
import com.uam.service.RoleService;
import com.uam.service.UserListService;
import com.uam.utils.*;
import com.uam.web.common.model.Result;
import com.uam.web.common.utils.AsyncFactory;
import com.uam.web.common.utils.AsyncManager;
import com.uam.web.common.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import com.uam.common.constant.CST;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author uam
 * @create 2023/11/29 22:11
 * @email uam@uam.com
 */
@Service
public class UserListServiceImpl implements UserListService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserListMapper userListMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RoleService roleService;

    @Override
    public Result login(String loginName, String password) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginName, password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (authenticate == null) {
            // 记录登录失败日志
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, "", Constants.FAIL, Constants.LOGIN_TITLE, Constants.LOGIN_MSG_ERROR));
            throw new CustomException("用户名或密码错误");
        }
        // 认证成功则通过jwt创建token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        Login login = LoginUser2Login.loginUser2Login(loginUser);
        String token = JwtUtil.createToken(login.getUser().getUserId(),
                login.getUser().getUserName(), login.getUser().getLoginName());
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("loginUser", login);
        // 把用户信息存入到redis
        String key = "login:" + login.getUser().getUserId();
        if (redisUtil.containsKey(key)) {
            redisUtil.del(key);
        }
        redisUtil.set(key, login, CST.LOGOUTTIME);
        // 记录登录成功日志
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, login.getUser().getUserName(), Constants.SUCCESS, Constants.LOGIN_TITLE, Constants.LOGIN_MSG_SUCCESS));
        return Result.createSuccess("登录成功", data);
    }

    @Override
    public IPage<UserListVO> selectUesrList(Integer pageNum, Integer pageSize, List<String> roleName, String loginName, String userName, String studentNumber) {

        Page<UserListVO> page = new Page(pageNum, pageSize);
        UserListDTO userListDTO = new UserListDTO();
        userListDTO.setUserName(userName);
        userListDTO.setLoginName(loginName);
        userListDTO.setStudentNumner(studentNumber);
        userListDTO.setRoleNames(roleName);
        //UserListBO userListBO = new UserListBO(roleName, loginName, userName, studentNumber);

        return userListMapper.selectUesrList(page, userListDTO);

    }

    @Override
    public String editPassword(HttpServletRequest request, String password, Long userId) {

        Long tokenId = TokenUtils.getUserIdForToken(request);
        Long editUserId = userId == null ? tokenId : userId;
        String ps = PasswordUtils.encoderPassword(password);
        int res = userListMapper.editPassword(editUserId, ps);
        return "修改成功";
    }

    @Override
    public Result deleteUserByUserIds(HttpServletRequest request, List<Long> userIds) {

        List<Long> adminIds = userListMapper.selectAdminIds();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.and(q -> {
            q.in("user_id", userIds);
            q.notIn(CollectionUtils.isNotEmpty(adminIds), "user_id", adminIds);
        });
        QueryWrapper<UserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.and(q -> {
            q.in("user_id", userIds);
            q.notIn(CollectionUtils.isNotEmpty(adminIds), "user_id", adminIds);
        });
        int delete = userRoleMapper.delete(userRoleQueryWrapper);
        int delete1 = userMapper.delete(userQueryWrapper);
        if (delete1 == 0) {
            throw new CustomException("删除用户失败");
        }
        if (delete == 0) {
            throw new CustomException("删除用户角色失败");
        }
        return Result.createSuccess();
    }

    @Override
    public Result addUser(Long userId, String loginName, String userName, String studentNumner, String roleName, String password) {
        checkUserNameExits(loginName);
        password = StringUtils.isEmpty(password) ? "ABC123@" : password;
        roleName = StringUtils.isEmpty(roleName) ? "学生" : roleName;
        userId = getMaxUserId() + 1;
        User user = new User();
        user.setLoginName(loginName);
        user.setUserName(userName);
        user.setStudentNumner(studentNumner);
        user.setPassword(PasswordUtils.encoderPassword(password));
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setUserId(userId);
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRole.setRoleId(roleService.getRoleIdByRoleName(roleName));
        int userRes = userMapper.insert(user);
        if (userRes == 0) {
            throw new CustomException("新增用户失败");
        }
        int userRoleRes = userRoleMapper.insert(userRole);
        if (userRoleRes == 0) {
            throw new CustomException("新增角色对应关系失败");
        }
        return Result.createSuccess("添加成功");
    }

    @Override
    public Result editUser(HttpServletRequest request, String password, String roleName, String loginName, String userName, String studentNumber, Long userId) {
        Long tokenId = TokenUtils.getUserIdForToken(request);
        Long editUserId = userId == null ? tokenId : userId;

        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", editUserId);
        updateWrapper.set(StringUtils.isNotEmpty(password), "password", PasswordUtils.encoderPassword(password));
        updateWrapper.set(StringUtils.isNotEmpty(loginName), "login_name", loginName);
        updateWrapper.set(StringUtils.isNotEmpty(userName), "user_name", userName);
        updateWrapper.set(StringUtils.isNotEmpty(studentNumber), "student_number", studentNumber);
        updateWrapper.set("update_time", LocalDateTime.now());
        if (StringUtils.isNotEmpty(roleName)) {
            Long roleId = roleService.getRoleIdByRoleName(roleName);
            UpdateWrapper<UserRole> userRoleUpdateWrapper = new UpdateWrapper<>();
            userRoleUpdateWrapper.eq("user_id", editUserId);
            userRoleUpdateWrapper.set("role_id", roleId);
            int update1 = userRoleMapper.update(null, userRoleUpdateWrapper);
            if (update1 == 0) {
                throw new CustomException("修改角色失败");
            }
        }

        int update = userMapper.update(null, updateWrapper);
        if (update == 0) {
            throw new CustomException("修改用户失败");
        }
        return Result.createSuccess();
    }

    @Override
    public Result logout(HttpServletRequest request) {
        Long userId = TokenUtils.getUserIdForToken(request);
        redisUtil.del("login:" + userId);
        User user = TokenUtils.getUserForToken(request).getUser();
        // 记录注销成功日志
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getLoginName(), user.getUserName(), Constants.SUCCESS, Constants.LOGOUT_TITLE, Constants.LOGOUT_MSG_SUCCESS));
        return Result.createSuccess("注销成功");
    }

    public Long getMaxUserId() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("max(user_id) as userId");
        User user = userMapper.selectOne(userQueryWrapper);
        return user == null ? 0L : user.getUserId();
    }

    public void checkUserNameExits(String loginName) {
        if (StringUtils.isNotEmpty(loginName)) {
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
            userLambdaQueryWrapper.eq(User::getLoginName, loginName);
            List<User> users = userMapper.selectList(userLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(users)) {
                throw new CustomException("登录名已存在");
            }

        }
    }

}
